package top.pengdong.pictureShare.tweet.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import cn.hutool.extra.qrcode.QrConfig;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import org.springframework.transaction.annotation.Transactional;
import top.pengdong.pictureShare.common.model.*;
import top.pengdong.pictureShare.common.utils.Address;
import top.pengdong.pictureShare.common.utils.IPAddress;
import top.pengdong.pictureShare.common.utils.OauthUtils;
import top.pengdong.pictureShare.common.utils.Tool;
import top.pengdong.pictureShare.tweet.config.SensitiveWordConfig;
import top.pengdong.pictureShare.tweet.dao.PsTweetDao;
import top.pengdong.pictureShare.tweet.dao.PsTweetImgDao;
import top.pengdong.pictureShare.tweet.dao.PsTweetLikeForwardDao;
import top.pengdong.pictureShare.tweet.entity.*;
import top.pengdong.pictureShare.tweet.handle.ListenHandler;
import top.pengdong.pictureShare.tweet.service.PsTweetImgService;
import top.pengdong.pictureShare.tweet.service.PsTweetLikeForwardService;
import top.pengdong.pictureShare.tweet.service.PsTweetService;

import javax.servlet.http.HttpServletRequest;

@Slf4j
@Service("psTweetService")
public class PsTweetServiceImpl extends ServiceImpl<PsTweetDao, PsTweetEntity> implements PsTweetService {

    @Autowired
    private PsTweetImgDao psTweetImgDao;

    @Autowired
    private TimeSchedulingService timeSchedulingService;

    @Autowired
    private PsTweetLikeForwardDao psTweetLikeForwardDao;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private PsTweetDao psTweetDao;


    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PsTweetEntity> page = this.page(
                new Query<PsTweetEntity>().getPage(params),
                new QueryWrapper<PsTweetEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 根据文章id生成二维码
     * @param id
     * @return
     */
    @Override
    public String createQR_code(Long id) {
        QrCodeUtil.generate(
                Address.DOMAIN + "/tweet/tweet_info/" + id, //二维码内容
                QrConfig.create().setImg(Address.FILEPATH + "/logo.jpg").setWidth(300).setHeight(300), //附带logo
                FileUtil.file(Address.FILEPATH + "/TWEET_" + id + ".jpg")  //写出到的文件
        );
        return "/TWEET_" + id + ".jpg";
    }

    /**
     * 生成二维码
     * @param psTweet
     * @return
     */
    @Override
    public Long saveWithCode(PsTweetEntity psTweet) {
        baseMapper.insert(psTweet);
        Long insert = psTweet.getId();
        psTweet.setId(insert);
        // 生成二维码链接
        String qr_code = this.createQR_code(insert);
        psTweet.setQrCode(qr_code);
        this.updateById(psTweet);
        return insert;
    }


    /**
     * 获取分享码
     * @param tweetId
     * @return
     */
    @Override
    public R shareWithCode(Long tweetId) {
        PsTweetEntity byId = this.getById(tweetId);
        if (byId == null || byId.getIsForward() == 0) return R.error(401, "该文章禁止分享");
        Map<String, String> map = new HashMap<>();
        // TODO 考虑要不要加上一个 随机码进行判断添加功能
        map.put("qr_code", byId.getQrCode());
        map.put("url", Address.DOMAIN + "/tweet/tweet_info/" + tweetId);
        // 添加转发数据到数据库上，同时更新到 redis 上

        return R.ok("转发信息").put("result", map);
    }

    @Cacheable(value={"TWEET_INFO"},key="'tweet_' + #id") // 指定key值为方法名字
    @Override
    public R getTweetInfo(Long id) {
        //TODO 记录用户浏览数据，这块有bug，不能判断 用户 id 因为权限写死
        PsTweetEntity psTweet = this.getById(id);
        if (psTweet == null) return R.error("参数错误");
        // System.out.println(psTweet);
        List<String> imags = psTweetImgDao.selectList(new QueryWrapper<PsTweetImgEntity>()
                        .eq("tweet_id", psTweet.getId()))
                .stream().map(PsTweetImgEntity::getImgUrl).collect(Collectors.toList());
        psTweet.setImages(imags);
        this.getTweetUserInfo(psTweet);
        // 查看是不是发布的文章
        if (psTweet.getIsPublish() == 1) {
            return R.ok().put("result", psTweet);
        } else {
            return R.error(ResultCode.UN_PUBLISH.getCode(), ResultCode.UN_PUBLISH.getMsg());
        }
    }

    /**
     * 添加文章
     * @param psTweet
     * @param request
     * @return
     */
    @Transactional
    @Override
    public R addTweet(PsTweetEntity psTweet, HttpServletRequest request, String userId) {
        if (psTweet.getImages() != null && psTweet.getImages().size() > 9) {
            return R.error(ResultCode.OVER_IMAGE.getCode(), ResultCode.OVER_IMAGE.getMsg());
        }
        TUsersEntity userInfo = this.baseMapper.getUserInfo(Long.valueOf(userId));
        if (userInfo.getStatus() == 0) {
            return R.error(ResultCode.USER_IS_BAN.getCode(), ResultCode.USER_IS_BAN.getMsg());
        }
        psTweet.setUserId(Long.valueOf(userId));
        String ipAddr = IPAddress.getIpAddr(request);
        psTweet.setLocation(ipAddr);

        psTweet.setContent(SensitiveWordConfig.sensitiveWordFiltering(psTweet.getContent()));
        // 获取ip属地操作
        psTweet.setIpAddress(Tool.getAddress(ipAddr));
        psTweet.setStatus(1);
        if (psTweet.getIsForward() == null)psTweet.setIsForward(1);
        if (psTweet.getIsLike() == null)psTweet.setIsLike(1);
        if (psTweet.getIsCollection() == null)psTweet.setIsCollection(1);
        if (psTweet.getIsOriginal() == null)psTweet.setIsOriginal(1);
        if (psTweet.getIsPublish() == null)psTweet.setIsPublish(1);
        if (psTweet.getIsComment() == null)psTweet.setIsComment(1);
        psTweet.setCollectionCount(0);
        psTweet.setForwardCount(0);
        psTweet.setLikeCount(0);
        psTweet.setCommentCount(0);
        psTweet.setViewCount(0);

        // 存储二维码
        Long id = this.saveWithCode(psTweet);
        // 获取对应id进行存储图片
        if (psTweet.getImages() == null) {
            return R.ok("没有图片,上传成功");
        }
        for (String str : psTweet.getImages()) {
            PsTweetImgEntity psTweetImgEntity = new PsTweetImgEntity();
            psTweetImgEntity.setImgUrl(str);
            psTweetImgEntity.setTweetId(id);
            psTweetImgDao.insert(psTweetImgEntity);
        }

        // 删除文章缓存 ，以便于更新数据库操作
        try {
            redisTemplate.delete(SysConstant.NEW_SWEET);
        } catch (Exception e) {
            System.out.println(e);
        }

        return R.ok("上传成功");
    }


    /**
     * 保存文章
     * @param psTweet
     * @return
     */
    @Transactional
    @Override
    public R updateTweet(PsTweetEntity psTweet) {
        LoginVal loginVal = OauthUtils.getCurrentUser();
        TUsersEntity userInfo = this.baseMapper.getUserInfo(Long.valueOf(loginVal.getUserId()));
        if (userInfo.getStatus() == 0) {
            return R.error(ResultCode.USER_IS_BAN.getCode(), ResultCode.USER_IS_BAN.getMsg());
        }
        PsTweetEntity byId = this.getById(psTweet);
        if (byId.getUserId() != Long.parseLong(loginVal.getUserId())) {
            return R.error(ResultCode.NO_PERMISSION.getCode() ,ResultCode.NO_PERMISSION.getMsg());
        }
        // 进行文章的修改
        this.updateById(psTweet);
        // 修改图片的状态，对不存在的图片进行添加或者在修改，对于已经存在的图片不进行修改
        List<PsTweetImgEntity> tweet_id = psTweetImgDao.selectList(new QueryWrapper<PsTweetImgEntity>()
                .eq("tweet_id", byId.getId()));

        for (PsTweetImgEntity ps: tweet_id) {
            // 不存在图片所以
            int i1 = -1;
            if (psTweet.getImages() != null && psTweet.getImages().size() > 0)
                i1 = psTweet.getImages().indexOf(ps.getImgUrl());
            if (i1 < 0) {
                // 不存在图片进行图片删除操作
                psTweetImgDao.deleteById(ps);
            } else {
                // 移除已经修改的 图片 剩下的就是还没有添加的图片
                psTweet.getImages().remove(i1);
            }
        }
        // 添加修改存在的图片
        if (psTweet.getImages() != null)
            for (String imgUrl : psTweet.getImages()) {
                PsTweetImgEntity psTweetImgEntity = new PsTweetImgEntity();
                psTweetImgEntity.setImgUrl(imgUrl);
                psTweetImgEntity.setTweetId(psTweet.getId());
                psTweetImgDao.insert(psTweetImgEntity);
            }

        return R.ok("修改成功");
    }

    /**
     * 删除文章操作
     * @param tweetId
     * @return
     */
    @Transactional
    @Override
    public R deleteTweet(Long tweetId) {
        LoginVal loginVal = OauthUtils.getCurrentUser();
        PsTweetEntity byId = this.getById(tweetId);
        log.info("用户删除文章 ：{}" + loginVal + tweetId);
        if (loginVal == null || byId.getUserId() != Long.parseLong(loginVal.getUserId())) {
            return R.error(ResultCode.NO_PERMISSION.getCode() ,ResultCode.NO_PERMISSION.getMsg());
        }
        // 不会删除，只是修改状态码进行修改
        // byId.setStatus(0);
        psTweetDao.deleteById(byId);
        // 同时删除图片的状态码
        List<PsTweetImgEntity> tweet_id = psTweetImgDao.selectList(new QueryWrapper<PsTweetImgEntity>()
                .eq("tweet_id", byId.getId()));
        for (PsTweetImgEntity ps: tweet_id) {
            psTweetImgDao.deleteById(ps);
        }
        // 删除用户分享或者是收藏的记录信息
        psTweetLikeForwardDao.delete(new QueryWrapper<PsTweetLikeForwardEntity>()
                .eq("tweet_id", byId.getId()));

        return R.ok("删除成功");
    }

    /**
     * 获取文章图片 同时获取用户信息操作
     * @param list
     */
    @Override
    public void getTweetImages(List<PsTweetEntity> list) {
        for (PsTweetEntity psTweet : list) {
            List<String> imags = psTweetImgDao.selectList(new QueryWrapper<PsTweetImgEntity>()
                            .eq("tweet_id", psTweet.getId()))
                    .stream().map(PsTweetImgEntity::getImgUrl).collect(Collectors.toList());
            psTweet.setImages(imags);
            getTweetUserInfo(psTweet);
        }
    }

    /**
     *  获取最新文章
     * @param currPage
     * @param limit
     * @return
     */
    @Override
    public R getViewShow(Integer currPage, Integer limit) {
        // 优化问题，redis 获取最新文章
        // redis 设置60s更新时间 同时记住有新文章的时候删除

        if (redisTemplate.opsForValue().get(SysConstant.NEW_SWEET + ":" + "tweets_" + currPage + "_" + limit) != null) {
            return  R.ok("最新文章").put("result", redisTemplate.opsForValue().get(
                    SysConstant.NEW_SWEET + ":" + "tweets_" + currPage + "_" + limit));
        }

        Page<PsTweetEntity> Tpage = this.page(
                new Page<PsTweetEntity>(currPage, limit),
                new QueryWrapper<PsTweetEntity>()
                        .eq("is_publish", 1)
                        .orderByDesc("create_time")
        );
        // 获取图片操作
        getTweetImages(Tpage.getRecords());
        PageUtils pageUtils = new PageUtils(Tpage);
        // 获取用户 名称和 头像

        redisTemplate.opsForValue().set(SysConstant.NEW_SWEET + ":" + "tweets_" + currPage + "_" + limit, pageUtils, 10, TimeUnit.SECONDS);
        return R.ok("最新文章").put("result", pageUtils);
    }


    /**
     * 查看文章更新
     * @param psTweet
     * @return
     */
    @Override
    public Boolean updateNumById(PsTweetEntity psTweet) {
        return baseMapper.updateNumById(psTweet) > 0;
    }

    /**
     * 获取用户状态 点赞操作等
     * @param aid
     * @return
     */
    @Override
    public R getUserStatus(Long[] aid) {
        LoginVal loginVal = OauthUtils.getCurrentUser();
        if (loginVal == null) {
            return R.error(ResultCode.CLIENT_AUTHENTICATION_FAILED.getCode(),
                    ResultCode.CLIENT_AUTHENTICATION_FAILED.getMsg());
        }
        Long userId = Long.valueOf(loginVal.getUserId());
        List<UserLikeCollection> list = new ArrayList<>();
        for (long id : aid) {
            UserLikeCollection userLikeCollection = new UserLikeCollection();
            userLikeCollection.setAid(id);
            // TODO 后面换成redis
            List<PsTweetLikeForwardEntity> LCList = psTweetLikeForwardDao.selectList(
                    new QueryWrapper<PsTweetLikeForwardEntity>()
                            .eq("user_id", Long.valueOf(loginVal.getUserId()))
                            .eq("tweet_id", id)
            );
            for (PsTweetLikeForwardEntity psTweetLikeForwardEntity : LCList) {
                if (psTweetLikeForwardEntity.getType() == 0) {
                    userLikeCollection.setLike(true);
                }
                if (psTweetLikeForwardEntity.getType() == 1) {
                    userLikeCollection.setShare(true);
                }
                if (psTweetLikeForwardEntity.getType() == 2) {
                    userLikeCollection.setCollection(true);
                }
            }

            // 查看文章关注问题
            if (psTweetDao.getUserRelation(userId, id) > 0) {
                userLikeCollection.setRelation(true);
            }

            list.add(userLikeCollection);
        }

        return R.ok("返回用户查询的点赞分享收藏状态").put("result", list);
    }

    /**
     * 获取对应类型的文章，像热点文章
     * 收藏文章
     * @param type
     * @return
     */
    @Override
    public Object getTypeTweets(String type, Integer currPage, Integer limit) {

        Object o = redisTemplate.opsForValue()
                .get(type + ":" + currPage + "_" + limit);
        // System.out.println(type + ":" + currPage + "_" + limit);
        if (o == null) {
            timeSchedulingService.GetHotSweets(currPage, limit);
            // list = (List<PsTweetEntity>) redisTemplate.opsForValue().get(type);
            o = redisTemplate.opsForValue()
                    .get(type + ":" + currPage + "_" + limit);
        }
        return o;
    }


    /**
     * 获取文章的 浏览数据，转发数据，收藏数据，分享数据，评论数据集合 ——TODO 重构
     * @param aid
     * @return
     */
    @Override
    public R getTweetCount(Long aid) {
        int like_count =  redisTemplate.opsForZSet().score(ListenHandler.LIKE_KEY, aid.toString()).intValue();
        int forward_count =  redisTemplate.opsForZSet().score(ListenHandler.FORWARD_KEY, aid.toString()).intValue();
        int view_count =  redisTemplate.opsForZSet().score(ListenHandler.VIEW_KEY, aid.toString()).intValue();
        int collection_count =  redisTemplate.opsForZSet().score(ListenHandler.COLLECTION_KEY, aid.toString()).intValue();
        int comment_count =  redisTemplate.opsForZSet().score(ListenHandler.COMMENT_KEY, aid.toString()).intValue();

        Map<String, Integer> map = new HashMap<>();
        map.put("like_count", like_count);
        map.put("share_count", forward_count);
        map.put("view_count", view_count);
        map.put("collection_count", collection_count);
        map.put("comment_count", comment_count);
        return R.ok("获取文章浏览量、收藏量等数据").put("result", map);
    }

    @Override
    public PageUtils getUserTweets(Long uid, Integer currPage, Integer limit) {
        IPage<PsTweetEntity> page = this.page(
                new Page<>(currPage, limit),
                new QueryWrapper<PsTweetEntity>()
                        .eq("user_id", uid)
        );
        // 获取图片操作
        getTweetImages(page.getRecords());
        return new PageUtils(page);
    }

    /**
     * 获取分类信息
     * @param category
     * @param currPage
     * @param limit
     * @return
     */
    @Override
    public R getCategoryList(Integer category, Integer currPage, Integer limit) {
        IPage<PsTweetEntity> page = this.page(
                new Page<PsTweetEntity>(currPage, limit),
                new QueryWrapper<PsTweetEntity>()
                        .eq("is_publish", 1)
                        .eq("label_id", category)
        );
        getTweetImages(page.getRecords());
        return R.ok("分类数据返回").put("result", new PageUtils(page));
    }

    /**
     * 添加 文章头像昵称
     */
    @Override
    public PsTweetEntity getTweetUserInfo(PsTweetEntity psTweet) {
        TUsersEntity userInfo = this.baseMapper.getUserInfo(psTweet.getUserId());
        psTweet.setNickname(userInfo.getNickname());
        psTweet.setAvatar(userInfo.getAvatar());
        return psTweet;
    }

    /**
     * 判断文章是否被点赞收藏
     */
    public PsTweetEntity hasTweetLikeCollection(PsTweetEntity psTweet) {
        // 查看点赞操作
        PsTweetLikeForwardEntity one = psTweetLikeForwardDao.selectOne(new QueryWrapper<PsTweetLikeForwardEntity>()
                .eq("type", 0)
                .eq("user_id", psTweet.getUserId())
                .eq("tweet_id", psTweet.getId())
        );
        if (one != null) psTweet.setHad_like(true);

        // 查看点赞操作
        one = psTweetLikeForwardDao.selectOne(new QueryWrapper<PsTweetLikeForwardEntity>()
                .eq("type", 1)
                .eq("user_id", psTweet.getUserId())
                .eq("tweet_id", psTweet.getId())
        );
        if (one != null) psTweet.setHad_collection(true);
        return psTweet;
    }

    @Override
    public R searchTweet(String key, Integer currPage, Integer limit) {
        IPage<PsTweetEntity> page = this.page(
                new Page<PsTweetEntity>(currPage, limit),
                new QueryWrapper<PsTweetEntity>()
                        .apply("MATCH(`content`) AGAINST ('" + key + "' IN NATURAL LANGUAGE MODE)")
        );
        getTweetImages(page.getRecords());
        return R.ok("查询结果如下").put("result", new PageUtils(page));
    }

    /**
     * 获取统计数据，从redis 获取
     * @return
     */
    @Override
    public List getCountList() {
        Map<String, PsCount> map = redisTemplate.opsForHash().entries(SysConstant.COUNT_SUM);
        List<Object> list = Arrays.asList(map.values().toArray());
        list.sort(Comparator.comparingInt(o -> ((PsCount) o).getId()));
        return list.subList(list.size() - 7, list.size());
    }
}